package com.tf_cut.backend.request.util;

import com.tf_cut.backend.request.MybankApiException;
import com.tf_cut.backend.seller.enums.MybankApiExceptionEnum;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class JaxbUtil {

    private volatile static Map<String, JAXBContext> jaxbContextMap = new ConcurrentHashMap<String, JAXBContext>();

    private static JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException {
        JAXBContext jaxbContext = jaxbContextMap.get(clazz.getName());
        if (jaxbContext == null) {
            synchronized (JaxbUtil.class) {
                jaxbContext = jaxbContextMap.get(clazz.getName());
                if (jaxbContext == null) {
                    jaxbContext = JAXBContext.newInstance(clazz);
                    jaxbContextMap.put(clazz.getName(), jaxbContext);
                }
            }
        }
        return jaxbContext;
    }

    /**
     * JavaBean转换成XML
     *
     * @param obj     领域对象实体
     * @param charset 字符编码 UTF-8
     * @return XML字符串
     */
    public static String convertToXml(Object obj, String charset) throws MybankApiException {
        String result = null;
        try {
            JAXBContext context = getJAXBContext(obj.getClass());
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, charset);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
//            marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {
//                public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException {
//                    writer.write(ch, start, length);
//                }
//            });
            StringWriter writer = new StringWriter();
            marshaller.marshal(obj, writer);
            result = writer.toString();
        } catch (JAXBException e) {
            throw new MybankApiException(MybankApiExceptionEnum.LOAD_JAXB_CONTEXT_ERROR,e);
        } catch (Exception e) {
            throw new MybankApiException(MybankApiExceptionEnum.XML_CONVERT_ERROR,e);
        }
        return result;
    }

    /**
     * xml转换成JavaBean
     *
     * @param xmlContent XML字符串
     * @param tClass     领域对象类型
     * @return 领域对象
     */
    public static <T> T converyToJavaBean(String xmlContent, Class<T> tClass) throws MybankApiException {
        T t = null;
        try {
            JAXBContext context = getJAXBContext(tClass);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            t = (T)unmarshaller.unmarshal(new StringReader(xmlContent));
        } catch (JAXBException e) {
            throw new MybankApiException(MybankApiExceptionEnum.LOAD_JAXB_CONTEXT_ERROR,e);
        } catch (Exception e) {
            throw new MybankApiException(MybankApiExceptionEnum.XML_CONVERT_ERROR,e);
        }
        return t;
    }
}